#ifndef _TBFILE_H_
#define _TBFILE_H_

#include "TBSettings.h"

#include "TBString2.h"

#include <stdio.h>

namespace tb
{

	class TB_DLL_FUNC File
	{
	
	public:

		enum OpenMode
		{
			eOpenMode_AbsolutePath = (1 << 0),
			eOpenMode_RelativePath = (1 << 1),
			eOpenMode_Read         = (1 << 2),
			eOpenMode_Write        = (1 << 3),
			eOpenMode_Binary       = (1 << 4),
			eOpenMode_Text         = (1 << 5),
			eOpenMode_Append       = (1 << 6),
			eOpenMode_Truncate     = (1 << 7),
			eOpenMode_ReadWrite    = eOpenMode_Read | eOpenMode_Write,
		};

		enum SeekMode
		{
			eSeekMode_Start        = SEEK_SET,
			eSeekMode_Current      = SEEK_CUR,
			eSeekMode_End          = SEEK_END
		};
	
		File();
		File(const char* a_FileName);
		File(const char* a_FileName, unsigned int a_Options);
		~File();
	
		bool IsOpen();
		bool IsReadable();
		bool IsWritable();
		bool IsEndOfFile();

		bool Open(unsigned int a_Options = eOpenMode_Read);
		bool Open(const char* a_FileName, unsigned int a_Options = eOpenMode_Read);
		unsigned int GetOpenMode() { return m_Mode; }

		template <typename D> 
		bool Read(D* a_Target, unsigned int a_Amount = 1);

		bool ReadLine(String& a_Target);

		bool Write();
		bool Flush();
		bool Seek(int a_Offset, SeekMode a_Mode = eSeekMode_Current);

		char* GetExtension();
		char* GetPath();

		bool Close();

	private:

		FILE* m_Handle;
		char m_Path[_MAX_PATH];
		size_t m_Offset;
		unsigned int m_Mode;
	
	}; // class File

	template <typename D> 
	inline bool File::Read(D* a_Target, unsigned int a_Amount)
	{
		if (!IsReadable()) { return false; }

		size_t bytes = sizeof(D) * a_Amount;
		size_t result = fread(a_Target, bytes, (size_t)a_Amount, m_Handle);
		if (result != bytes)
		{
			return (feof(m_Handle));
		}

		m_Offset += bytes;
		return true;
	}

}; // namespace tb
	
#endif